package tgc.edu.tms.web.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import tgc.edu.tms.custom.AjaxResult;
import tgc.edu.tms.custom.CommonController;
import tgc.edu.tms.custom.ExportExcel;
import tgc.edu.tms.custom.TimeUtils;
import tgc.edu.tms.entity.ClassSchedule;
import tgc.edu.tms.entity.Classroom;
import tgc.edu.tms.entity.CourseCategory;
import tgc.edu.tms.entity.EducationalPlanner;
import tgc.edu.tms.entity.FlowTable;
import tgc.edu.tms.entity.Jcb;
import tgc.edu.tms.entity.Schoolyear;
import tgc.edu.tms.entity.SysUser;
import tgc.edu.tms.entity.TbClass;
import tgc.edu.tms.entity.Teacher;
import tgc.edu.tms.entity.Xqsj;
import tgc.edu.tms.security.UserUtils;
import tgc.edu.tms.service.ClassScheduleService;
import tgc.edu.tms.service.ClassroomService;
import tgc.edu.tms.service.EducationalPlannerService;
import tgc.edu.tms.service.FlowTableService;
import tgc.edu.tms.service.JcbService;
import tgc.edu.tms.service.ProfessionService;
import tgc.edu.tms.service.SchoolyearService;
import tgc.edu.tms.service.TbClassService;
import tgc.edu.tms.service.TeacherService;
import tgc.edu.tms.service.XqsjService;
import tgc.edu.tms.web.form.ClassScheduleForm;

@Controller
@RequestMapping(value = "/classSchedule")
public class ClassScheduleController extends CommonController<ClassSchedule, Integer, ClassScheduleForm> {
	@Autowired
	private UserUtils userUtils;
	@Autowired
	private ProfessionService proservice;
	@Autowired
	private ClassroomService classroomService;
	@Autowired
	private JcbService jcbService;
	@Autowired
	private TbClassService tbClassService;
	@Autowired
	private SchoolyearService schoolyerarService;
	@Autowired
	private ClassScheduleService classScheduleService;
	@Autowired
	private EducationalPlannerService educationalPlannerService;
	@Autowired
	private FlowTableService flowTableService;
	@Autowired
	private XqsjService xqsjService;
	@Autowired
	private TeacherService teacherService;

	@RequestMapping(value = "/classroom")
	@ResponseBody
	public Object classroom() {
		List<Classroom> list = classroomService.findAll();
		return list;
	}

	@RequestMapping(value = "/getSkjc")
	@ResponseBody
	public Object getSkjc(String skxq) {
		List<Jcb> list = jcbService.findBySkxq(skxq);
		return list;
	}

	@RequestMapping(value = "/tbclass")
	@ResponseBody
	public Object tbclass(Integer id) {
		List<TbClass> list = tbClassService.findByprofessionID(id);
		return list;
	}

	@RequestMapping(value = "/kcjhandxq")
	@ResponseBody
	private Object kcjhandxq(Integer profesion, Integer schoolyearId) {
		List<EducationalPlanner> ep = educationalPlannerService
				.findBySchoolyearIdAndCurriculumProfessionId(schoolyearId, profesion);
		return ep;
	}
	
	@RequestMapping(value = "/xnxq")
	@ResponseBody
	public Object xnxq() {
		List<Schoolyear> list = schoolyerarService.findAll();
		return list;
	}

	@Override
	public Object save(ClassScheduleForm form) {
		try {
			ClassSchedule model = new ClassSchedule();
			Integer id = form.getModelid();
			if (id != null) {
				model = classScheduleService.findById(id);
				Integer classroomid = form.getClassroomid();
				Classroom classroom = classroomService.findById(classroomid);
				model.setClassroom(classroom);
				Integer skjc = form.getSkjc();
				Jcb jcb = jcbService.findById(skjc);
				model.setJcb(jcb);
				EducationalPlanner ep = educationalPlannerService.findById(form.getKcjhid());
				model.setEp(ep);
				/*
				 * Integer xnxqid = form.getXnxqid(); Schoolyear schoolyear =
				 * schoolyearService.findById(xnxqid); model.setScyear(schoolyear);
				 */

				classScheduleService.save(model);
			}
			Integer classroomid = form.getClassroomid();
			Classroom classroom = classroomService.findById(classroomid);
			model.setClassroom(classroom);
			Integer skjc = form.getSkjc();
			Jcb jcb = jcbService.findById(skjc);
			model.setJcb(jcb);

			EducationalPlanner ep = educationalPlannerService.findById(form.getKcjhid());
			model.setEp(ep);
			String str = "";
			for (TbClass c : ep.getTbclass()) {
				str += c.getName() + ",";
			}

			if (str != "") {
				String str2 = str.substring(0, str.length() - 1);
				model.setSearcherclass(str2);
			}
			/*
			 * Integer xnxqid = form.getXnxqid(); Schoolyear schoolyear =
			 * schoolyearService.findById(xnxqid); model.setScyear(schoolyear);
			 */
			classScheduleService.save(model);
			return new AjaxResult("数据保存成功");
		} catch (Exception e) {
			return new AjaxResult(false, "数据保存失败");
		}
	}

	@Override
	public void edit(ClassScheduleForm form, ModelMap map) throws InstantiationException, IllegalAccessException {
		ClassSchedule model = new ClassSchedule();
		model = null;
		Integer id = form.getId();
		if (id != null) {
			model = classScheduleService.findById(id);
		}
		List<String> years = proservice.findAllYear();
		List<String> findAllXq = jcbService.findAllXq();
		map.put("xq", findAllXq);
		map.put("years", years);
		map.put("model", model);
	}

	// 获取所有年级信息
	@RequestMapping(value = "/findAllYear")
	@ResponseBody
	public Object findAllYear() {
		List<String> findAllYear = proservice.findAllYear();
		return findAllYear;
	}

	// 获取所有学年学期
	@RequestMapping(value = "/findAgcsSchoolyear")
	@ResponseBody
	public Object findAgcsSchoolyear() {
		Sort sort = new Sort(Sort.Direction.DESC, "id");
		List<Schoolyear> findAllYear = schoolyerarService.findAll(sort);
		return findAllYear;
	}

	// 获取该年级下所有专业信息
	@RequestMapping(value = "/yearChanges")
	@ResponseBody
	public Object yearChanges(String year) {
		List<String> findProfesionByYear = proservice.findProfesionByYear(year);
		return findProfesionByYear;
	}

	// 获取该年级该专业下所有班级
	@RequestMapping(value = "/majorChange")
	@ResponseBody
	public Object majorChange(String major, String years) {
		Integer proId = proservice.findIdByProfesionAndYear(major, years);
		List<TbClass> findByProfession_id = tbClassService.findByProfession_id(proId);
		return findByProfession_id;
	}

	// 查找所有学年学期
	@RequestMapping(value = "/findSchoolYear")
	@ResponseBody
	public Object schoolyear(String year) {
		Integer years = Integer.parseInt(year);// 第一年
		Integer years2 = years + 1;// 第二年
		Integer years3 = years2 + 1;// 第三年
		Integer years4 = years3 + 1;// 第四年
		List<Schoolyear> sc = null;
		Specification<Schoolyear> spec = new Specification<Schoolyear>() {
			@Override
			public Predicate toPredicate(Root<Schoolyear> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
				HashSet<Predicate> rules = new HashSet<>();
				Predicate predicate = null;
				rules.add(criteriaBuilder.like(root.get("xnxq"), years + "年秋季学期" + "%"));

				rules.add(criteriaBuilder.like(root.get("xnxq"), years2 + "%"));

				rules.add(criteriaBuilder.like(root.get("xnxq"), years3 + "%"));

				rules.add(criteriaBuilder.like(root.get("xnxq"), years4 + "年春季学期" + "%"));

				predicate = criteriaBuilder.or(rules.toArray(new Predicate[rules.size()]));
				return predicate;
			}
		};
		Sort sort = new Sort(Sort.Direction.DESC, "id");
		sc = schoolyerarService.findAll(spec, sort);
		return sc;
	}

	// 获取所有教师
	@RequestMapping(value = "/getTeacher")
	@ResponseBody
	public Object getTeacher() {
		List<Teacher> list = teacherService.findAll();
		return list;
	}

	@Override
	public void manage(ModelMap map) {
		List<String> findAllYear = proservice.findAllYear();
		map.put("year", findAllYear);
	}

	@Override
	public Specification<ClassSchedule> buildSpec(ClassScheduleForm form) {
		Specification<ClassSchedule> spec = new Specification<ClassSchedule>() {

			@Override
			public Predicate toPredicate(Root<ClassSchedule> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				if (StringUtils.hasText(form.getYear())) {
					rules.add(cb.like(root.get("ep").get("curriculum").get("profession").get("year"),
							"%" + form.getYear() + "%"));
				}
				if (StringUtils.hasText(form.getCollege())) {
					rules.add(cb.like(root.get("ep").get("curriculum").get("profession").get("profesion"),
							"%" + form.getCollege() + "%"));
				}
				if (StringUtils.hasText(form.getMajor())) {
					rules.add(cb.like(root.get("searcherclass"), "%" + form.getMajor() + "%"));
				}
				if (StringUtils.hasText(form.getSchoolyear())) {
					rules.add(cb.like(root.get("ep").get("schoolyear").get("xnxq"), "%" + form.getSchoolyear() + "%"));
				}
				if (StringUtils.hasText(form.getSearchTeacher())) {
					rules.add(cb.equal(root.get("ep").get("teacher").get("name"), form.getSearchTeacher()));
				}
				if (StringUtils.hasText(form.getSearch())) {
					Predicate kcmcname = cb.like(root.get("ep").get("curriculum").get("kcmc"),
							"%" + form.getSearch() + "%");
					Predicate teachername = cb.like(root.get("ep").get("teacher").get("name"),
							"%" + form.getSearch() + "%");
					Predicate jcsj = cb.like(root.get("jcb").get("jcsj"), "%" + form.getSearch() + "%");
					Predicate khfs = cb.like(root.get("ep").get("curriculum").get("khfs"),
							"%" + form.getSearch() + "%");
					Predicate serialNumber = cb.like(root.get("classroom").get("serialNumber"),
							"%" + form.getSearch() + "%");
					Predicate rules2 = cb.or(kcmcname, teachername, jcsj, khfs, serialNumber);
					rules.add(rules2);
				}
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}

		};
		return spec;
	}

	/**
	 * 生成授课记录/流水表
	 * 
	 * @return
	 */
	@RequestMapping(value = "/generateTab")
	@ResponseBody
	public Object generateUp(String startTime, String endTime) {
		try {
			List<ClassSchedule> allData = classScheduleService.findAll();
			List<FlowTable> allFlow = flowTableService.findAll();
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // 设置日期格式
			String dqTime = df.format(new Date()); // 当前时间
			String yearStr = dqTime.substring(0, 4); // 当前年份
			int year = Integer.parseInt(yearStr);
			int dqYear = year;
			String month = dqTime.substring(5, dqTime.length() - 3); // 当前月份
			String term = monthToTerm(month); // 获取学期
			if (term.equals("第一学期")) { // 第一学期获取开学时间应该减少一年(因为存在1月这个特殊情况)
				year--;
			}
			if (term.equals("第二学期")) {
				dqYear--;
			}
			Date beginDate = null; // 开始时间
			Date endDate = null; // 结束时间
			List<Xqsj> xqTime = xqsjService.findAll();
			for (Xqsj xq : xqTime) { // 找到当前年份对应的开学时间以及结束时间
				String str = xq.getXqks().substring(0, 4);
				if (str.equals("" + year + "")) {
					beginDate = df.parse(xq.getXqks());
					endDate = df.parse(xq.getXqjs());
					break;
				}
			}

			if (beginDate != null && endDate != null) {
				if (startTime != null && endTime != null) {
					if (beginDate.before(df.parse(startTime)) && endDate.after(df.parse(endTime))) {
						beginDate = df.parse(startTime);
						endDate = df.parse(endTime);
					} else {
						return "所选时间不在在校时间内！";
					}
				}
				Date date = beginDate;
				Calendar c = Calendar.getInstance();
				while (!date.equals(endDate)) { // 先删除已存在的流水表
					for (FlowTable f : allFlow) {
						Date parse = df.parse(f.getTime());
						if (date.equals(parse)) {
							flowTableService.delete(f);
						}
					}
					c.setTime(date);
					c.add(Calendar.DATE, 1); // 日期加1天
					date = c.getTime();
				}
				date = beginDate;
				while (!date.equals(endDate)) {
					String week = dateToWeek(df.format(date));// 当前日期(date)对应的星期
					for (ClassSchedule cs : allData) {
						int csYear = Integer.parseInt(cs.getEp().getCurriculum().getProfession().getYear());// 数据中课程对应的年级
						if (yearToTerm(csYear, dqYear, month).equals(cs.getEp().getCurriculum().getKkxq())) { // 根据年级获得学期，学期对应才生成
							int beginzc = Integer.parseInt(cs.getEp().getQszc()); // 开始周次
							int endzc = Integer.parseInt(cs.getEp().getJszc()); // 结束周次
							int zc = dateToZc(df.format(beginDate), df.format(date)); // 当前周次
							if (zcUtils(beginzc, endzc, zc)) { // 周次对应才生成
								if (cs.getJcb().getXq().equals(week)) { // 星期对应才生成
									FlowTable flow = new FlowTable();
									String classes = "";
									Integer number = 0;
									for (TbClass t : cs.getTbclass()) {
										classes += t.getName() + ",";
										number += t.getNumber();
									}
									flow.setClasses(classes.substring(0, classes.length() - 1));
									flow.setCourse(cs.getEp().getCurriculum().getKcmc());
									flow.setClassRoom(cs.getClassroom().getSerialNumber());
									flow.setTeacher(cs.getEp().getTeacher().getName());
									flow.setZxs(cs.getEp().getCurriculum().getZongxs());
									flow.setTime(df.format(date));
									flow.setWeek(week);
									flow.setJc(cs.getJcb().getJcsj());
									flow.setYdrs(number);
									flow.setLd(cs.getClassroom().getLocation().getName());
									flow.setLc(cs.getClassroom().getFloor());
									String kclbs = "";
									for (CourseCategory category : cs.getEp().getCurriculum().getKclbs()) {
										kclbs += category.getType() + ",";
									}
									flow.setKclbs(kclbs.substring(0, kclbs.length() - 1));
									flow.setYear(cs.getEp().getCurriculum().getProfession().getYear());
									flow.setTerm(cs.getEp().getSchoolyear().getXnxq());
									flow.setXmh(cs.getEp().getXmh());
									flowTableService.save(flow);
								}
							}

						}

					}
					c.setTime(date);
					c.add(Calendar.DATE, 1); // 日期加1天
					date = c.getTime();
				}
			} else {
				return "当年开学时间或结束时间未指定！";
			}

		} catch (Exception e) {
			return "error";
		}
		return "ok";
	}

	/**
	 * 
	 * @param beginzc 开始周次
	 * @param endzc   结束周次
	 * @param zc      需判断的周次
	 * @return 周次在开始-结束周次之内返回1，否则0
	 */
	private boolean zcUtils(int beginzc, int endzc, int zc) {
		int[] list = new int[endzc - beginzc];
		for(int i = 0; i < list.length; i++) {
			list[i]=beginzc+i;
		}
		for (int i = 0; i < list.length; i++) {
			if (zc == list[i]) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 日期转星期
	 * 
	 * @param datetime
	 * @return
	 */
	public static String dateToWeek(String datetime) {
		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
		String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		Calendar cal = Calendar.getInstance(); // 获得一个日历
		Date datet = null;
		try {
			datet = f.parse(datetime);
			cal.setTime(datet);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
		if (w < 0)
			w = 0;
		return weekDays[w];
	}

	/**
	 * 根据年级判断学期
	 * 
	 * @param year   待测年级(如"2017"级)
	 * @param dqYear 当前年份
	 * @param month  当前月份
	 * @return
	 */
	public static String yearToTerm(int year, int dqYear, String month) {
		/*
		 * SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); String dqTime =
		 * df.format(new Date()); // 当前时间 String dqYearStr = dqTime.substring(0, 4); //
		 * 当前年份 int dqYear = Integer.parseInt(dqYearStr); // 当前年份 dqYear--; String month
		 * = dqTime.substring(5, dqTime.length() - 3); // 当前月份
		 */
		if (dqYear == year) {
			String term = monthToTerm(month);
			if ("第一学期".equals(term)) {
				return "一";
			}
			if ("第二学期".equals(term)) {
				return "二";
			}
		}
		if (dqYear - 1 == year) {
			String term = monthToTerm(month);
			if ("第一学期".equals(term)) {
				return "三";
			}
			if ("第二学期".equals(term)) {
				return "四";
			}
		}
		if (dqYear - 2 == year) {
			String term = monthToTerm(month);
			if ("第一学期".equals(term)) {
				return "五";
			}
			if ("第二学期".equals(term)) {
				return "六";
			}
		}

		return "无对应的学期，年级给错了？？";

	}

	/**
	 * 根据月份判断学期
	 * 
	 * @param month 要判断的月份
	 * @return
	 */
	public static String monthToTerm(String month) {
		String[] one = { "01", "02", "03", "04", "05", "06" };
		String[] two = { "07", "08", "09", "10", "11", "12" };

		for (String s : one) {
			if (month.equals(s)) {
				return "第二学期";
			}
		}
		for (String s : two) {
			if (month.equals(s)) {
				return "第一学期";
			}
		}
		return "无对应学期，月份给错了？？？";

	}

	/**
	 * 根据开学时间判断某时间对应的周次
	 * 
	 * @param beginDateStr 开学时间
	 * @param flagDateStr  要判断的时间
	 * @return 要判断的时间对应的周次
	 */
	public static int dateToZc(String beginDateStr, String flagDateStr) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Date keyDate, beginDate, endDate;
		try {
			keyDate = null;
			beginDate = df.parse(beginDateStr);
			endDate = df.parse(flagDateStr);
			String week = dateToWeek(beginDateStr);
			Calendar c = Calendar.getInstance();
			switch (week) {
			case "星期一":
				keyDate = beginDate;
				break;
			case "星期二":
				c.setTime(beginDate);
				c.add(Calendar.DATE, -1);
				keyDate = c.getTime();
				break;
			case "星期三":
				c.setTime(beginDate);
				c.add(Calendar.DATE, -2);
				keyDate = c.getTime();
				break;
			case "星期四":
				c.setTime(beginDate);
				c.add(Calendar.DATE, -3);
				keyDate = c.getTime();
				break;
			case "星期五":
				c.setTime(beginDate);
				c.add(Calendar.DATE, -4);
				keyDate = c.getTime();
				break;
			case "星期六":
				c.setTime(beginDate);
				c.add(Calendar.DATE, -5);
				keyDate = c.getTime();
				break;
			case "星期日":
				c.setTime(beginDate);
				c.add(Calendar.DATE, -6);
				keyDate = c.getTime();
				break;
			default:
				System.out.println("应该不存在此处错误，试着检查日期格式是否正确？");
				break;
			}

			int result = 0;
			c.setTime(df.parse(flagDateStr));
			int day1 = c.get(Calendar.DAY_OF_YEAR);
			c.setTime(keyDate);
			int day2 = c.get(Calendar.DAY_OF_YEAR);
			result = ((day1 - day2) / 7) + 1;
			return result;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return 0;

	}

	/**
	 * 导出报表
	 * 
	 * @return
	 */
	@RequestMapping(value = "/export")
	@ResponseBody
	public void export(HttpServletRequest request, HttpServletResponse response) throws Exception {
		List<ClassSchedule> list = classScheduleService.findAll();
		String title = "课程表";
		String[] columnName = new String[] { "序号", "课程", "学分", "总学时", "考核方式", "教师", "上课人数", "周次", "节次", "地点", "年纪",
				"专业", "学期" };
		List<Object[]> dataList = new ArrayList<Object[]>();
		for (ClassSchedule c : list) {
			String kcmc = c.getKcmc();
			float xf = c.getXf();
			Integer zongxs = c.getZongxs();
			String khfs = c.getKhfs();
			String teacherName = c.getTeacherName();
			Integer capacity = c.getTbclassNumber();
			String zc = c.getZc();
			String jcsj = c.getJcsj();
			String dd = c.getDd();
			String year = c.getYear();
			String profession = c.getProfession();
			String xnxq = c.getEp().getSchoolyear().getXnxq();
			Object[] objs = { kcmc, kcmc, xf, zongxs, khfs, teacherName, capacity, zc, jcsj, dd, year, profession,
					xnxq };
			dataList.add(objs);
		}
		// 实例化工具类
		ExportExcel ex = new ExportExcel(title, columnName, dataList, request, response);
		try {
			// 导出excel
			ex.export();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
